<?php

/**
 * @author Michael Schnyder
 * @version 2009-02-19
 */

require_once("FileManagerLibrary.class.php");

class FileManager {

	private $connectorUrl = "";
	
	// Urls foro the Tree-Connector and the File-Connector, @see setConnectorUrl
	private $treeConnectorUrl = "";
	private $fileConnectorUrl = "";
	
	// URL to the File wich imp,emnents the download Version fur Public Access
	private $publicFileGetUrl = "";
	
	//Public and internal Path to Icons (internal to check wich files exist)
	private $iconsUrl = "";

	//Array with all available Icons on System for Filytypes
	private $iconList = array();
	
	private $fmHttpVarsPrefix = "fm_";
	private $isSelectMode = true;
	
	
	private $passPhrase = "Blabliblablupp";
	
	private $libraries = array();
	
	public function __construct() {
		$this->setConnectorUrl("");
	}
	
	public function setConnectorUrl($s) {
		
		$this->treeConnectorUrl = $s . (is_numeric(stripos($s, "?",0))?"&":"?") . $this->fmHttpVarsPrefix."conn=tree";
		$this->fileConnectorUrl = $s . (is_numeric(stripos($s, "?",0))?"&":"?") .$this->fmHttpVarsPrefix."conn=file";
		
	}
	
	public function setPublicFileGetUrl($s) {
		$this->publicFileGetUrl = $s;
	}
	
	public function setIconsUrl($s) {
		$this->iconsUrl = $s;
	}
	
	public function setIconsLocalPath($s) {
		//$this->iconsLocalPath = $s;
		$files = @scandir($s);
		
		foreach ($files as $file) {
			
			$pathinfo = pathinfo($file);
			if(strtolower($pathinfo['extension'])=='png') {
				array_push($this->iconList, $pathinfo['filename']);
				//echo "found ".$pathinfo['filename']."\n";
			}
		}
		
	}
	
	public function setDialogMode() {
		$this->isSelectMode = true;
	}
	
	public function setDownloadMode() {
		$this->isSelectMode = false;
	}
	
	public function setPassPhrase($s) {
		$this->passPhrase = $s;
	}
	/**
	 * 
	 * @param $library FileManangerLibrary
	 * @return void
	 */
	public function addLibrary($library) {
		
		$library->setFileManager($this);
		$this->libraries[$library->getName()] = $library;
		
	}
	
	public function getIconUrl($ext) {
		//echo $ext;
		//print_r($this->iconList);
		
		// Try to find Icon
		if(in_array(strtolower($ext), $this->iconList)) {
			$name = strtolower($ext);
		}
		elseif(in_array(strtoupper($ext), $this->iconList)) {
			$name = strtoupper($ext);
		}
		else {
			$name = "Default";
		}
		//die($this->iconsUrl . "/" . $name . ".png");
		return $this->iconsUrl . "/" . $name . ".png";
	}
	/**
	 * 
	 * @param $id
	 * @return FileManagerLibrary
	 */
	private function getLibrary($id) {
		
		if(is_numeric($id)) {
			$i=0;
			foreach ($this->libraries as $lib) {
				if($i==$id) { return $lib; }
				$i++;
			}
		}
		else {
			return $this->libraries[$id];
		}
	}
	
	private function isSingleLibrary() {
		return count($this->libraries)==1; 
	}
	
	public function handleRequest() {
		
		if(isset($_GET[$this->fmHttpVarsPrefix.'conn'])) {
			$fm_mode = $_GET[$this->fmHttpVarsPrefix.'conn'];
			
			if($fm_mode=="tree") {
				$this->handleTreeRequest();
				return true;
			}
			elseif ($fm_mode=="file") {
				$this->handleFileRequest();
				return true;
			}
			
		}
		return false;
		
	}
	
	public function handleGetPublicFileRequest() {
		
		$ser_conf = base64_decode($_GET['c']);
		$ser_seal = $_GET['s'];
		
		$ser_seal_calc = md5($ser_conf . $this->passPhrase);
		if($ser_seal == $ser_seal_calc) {
			$conf = unserialize($ser_conf);
			
			$dir = $conf['dir'];
			$lib = unserialize($conf['lib']);
			
			$lib->downloadFile($dir);
		}
		else {
			echo "Invalid Link!";
		}
		
	}
	private function handleTreeRequest() {
		
		// Check wich Library should be used
		$dir = urldecode($_POST['dir']);
		$dir = str_replace("..", "", $dir);
		
		$l = null;
		$tree = array();
		
		//Root Folders?
		if($dir == "/" && !$this->isSingleLibrary()) {
			
			// Display all Libraries
			foreach ($this->libraries as $name => $library) {
				array_push($tree, array('name' => $name, 'type' => 'library'));
			}
			
		}
		else {

			$l = $this->getLibraryFromDir($dir);
			
			//Remove Library Name from dir if there are more than one Library
			if(!$this->isSingleLibrary()) {
				$libdir = substr($dir, strlen($l->getName()) + 1);
			}
			else {
				$libdir = $dir;
			}
			$tree = $l->getSubTree($libdir);
			
		}
		
		// Display SubTree
		$this->writeSubTree($dir, $tree);
		
	}
	
	private function getLibraryFromDir($dir) {
		
		// Check wich Library should be used
		if($this->isSingleLibrary()) {

			//If We only have a single Library, we can directly display the Contents of this Library
			$l = $this->getLibrary(0);
			
		}
		else {
			// Find the Currect Library and extract Dir from this Library
			$folders = explode("/", $dir);
			$libname = $folders[1];
			$l = $this->getLibrary($folders[1]);
		}
		
		return $l;
	}
	
	private function handleFileRequest() {
		
		$path = urldecode($_GET['path']);
		if(!$path) {
			$path = urldecode($_POST['currentpath']);
		}
		$path = str_replace("..", "", $path);
		
		$mode = $_GET[$this->fmHttpVarsPrefix.'mode'];
		if(!$mode) {
			$mode = $_POST[$this->fmHttpVarsPrefix.'mode'];
		}
		$l = $this->getLibraryFromDir($path);
		
		//Remove Library Name from dir if there are more than one Library
		if(!$this->isSingleLibrary()) {
			$libdir = substr($path, strlen($l->getName()) + 1);
		}
		else {
			$libdir = $path;
		}
		
		
		switch ($mode) {
			case "getfolder":
				$r = $l->getFolder($libdir);

				//Add Library Name to path if not singel Library is displayed
				if(!$this->isSingleLibrary()) {
					foreach ($r as $key => $value) {
						//echo $key."\n";
						$r[$key]['Path'] = "/" . $l->getName() . $r[$key]['Path'];
						
						if(isset($r[$key]['ThumbUrl']) && $r[$key]['ThumbUrl'] !=null) {
							$r[$key]['ThumbUrl'] = $this->fileConnectorUrl . "&" . $this->fmHttpVarsPrefix . "mode=getThumb&path=".$r[$key]['Path'] . $r[$key]['ThumbUrl'];
						}
						
						
					}
				}
				
				// Sort Listening
				uasort($r, __CLASS__."::sortFolderContents");
				break;
				
			case "getinfo":

				$r = $l->getInfo($libdir);
				// Add Library Path
				$r['Path'] = "/" . $l->getName() . $r['Path'];
				break;
				
			case "addfolder":
				
				$name = $_GET["name"];
				$created = $l->addFolder($libdir, $name);
				
				if($created==true || is_string($created)) {
					$r = array(
						"Parent" => $path, 
						"Name" => is_bool($created)?$name:$created,
						"Error" => "OK",
						"Code" => 0
					);
				}
				else {
					$r = array(
						"Error" => "Could not Create Folder '$name' in '$libdir",
						"Code" => -1
					);
				}
				break;
				
			case "add":
				
				$file = $_FILES['newfile'];
				$name = $file['name'];
				
				$saved = $l->addFile($libdir, $file);
				
				if($saved) {
					$r = array(
						"Path" => $path, 
						"Name" => is_bool($saved)?$name:$saved,
						"Error" => "OK",
						"Code" => 0
					);
				}
				else {
					$r = array(
						"Error" => "Could not save file '$name' in '$libdir",
						"Code" => -1
					);
				}
				break;
			
			case "download": 
				
				$l->downloadFile($libdir);
				break;
			
			case "getPublicFileUrl":
				
				$r['PublicFileUrl'] = $this->getPublicFileUrl($l, $libdir);
				break;
				
			case "rename":
				
				$name = $_GET["new"];
				$renamed = $l->rename($libdir, $name);
				
				if($renamed==true || is_string($renamed)) {
					$r = array(
						"Old Path" => $path, 
						"Old Name" => null,
						"New Path" => null,
						"New Name" => is_bool($renamed)?$name:$renamed,
						"Error" => "OK",
						"Code" => 0
					);
				}
				else {
					$r = array(
						"Error" => "Could not rename item!",
						"Code" => -1
					);
				}
				break;

			case "delete": 
				
				$deleted = $l->delete($libdir);
				
				if($deleted==true || is_string($deleted)) {
					$r = array(
						"Parent" => $path, 
						"Name" => is_bool($deleted)?$name:$deleted,
						"Error" => "OK",
						"Code" => 0
					);
				}
				else {
					$r = array(
						"Error" => "Could not delete item!",
						"Code" => -1
					);
				}
				break;
				
			case "getThumb":
				$l->getThumb($libdir);
				
				break;
								
		}
		
		die(json_encode($r));
	}
	
	/**
	 *  This Method is used, to acces a File in a Library from outside, without information about the Library.
	 *  So, the Library Specific Information is serialized an stored in the URL
	 *  
	 *  
	 */
	
	/**
	 * 
	 * @param $library FileManagerLibrary
	 * @param $path string
	 * @return string
	 */
	private final function getPublicFileUrl($library, $path) {
		
		$conf['lib'] = serialize($library);
		$conf['dir'] = $path;
		
		$ser_conf = serialize($conf);
		$ser_seal = md5($ser_conf . $this->passPhrase);
		
		return $this->publicFileGetUrl . ($this->publicFileGetUrl?"&":"?") . $this->fmHttpVarsPrefix."mode=downloadPublic&c=".base64_encode($ser_conf)."&s=".$ser_seal;
		
	} 
	
	
	private static function sortFolderContents($a, $b) {
		
		if($a['File Type'] == $b['File Type']) {
			if($a['Filename'] == $b['Filename']) {
				return 0;
			}
			else {
				return ($a['Filename'] < $b['Filename'] ? -1: +1);
			}
		}
		else {
			if($a['File Type']=='dir' && $b['File Type']!='dir') {
				return -1;
			}
			else {
				return +1;
			}
		}
		
	}
	
	private function writeSubTree($dir, $tree) {
		
		if(is_array($tree)) {

			echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
			foreach ($tree as $item) {

				if($item['type']=="library") {
					echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($dir . $item['name']) . "/\">Library " . htmlentities($item['name']) . "</a></li>";
				}
				elseif($item['type']=="directory") {
					echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($dir . $item['name']) . "/\">" . htmlentities($item['name']) . "</a></li>";
				}
				elseif($item['type']=="file") {
					echo "<li class=\"file ext_".$item['extension']."\"><a href=\"#\" rel=\"" . htmlentities($dir . $item['name']) . "\">" . htmlentities($item['name']) . "</a></li>";
				}

			}
			
			echo "</ul>";
			
		}	
	}
		
	public function writeFileManager($returnText=false) {
		
		$text ="<script language='Javascript'>\n";
		$text.="    var treeConnector  = '$this->treeConnectorUrl';\n";
		$text.="    var fileConnector  = '$this->fileConnectorUrl';\n";
		$text.="    var httpVarsPrefix = '$this->fmHttpVarsPrefix';\n";
		$text.="    var isSelectMode = ".($this->isSelectMode?"true":"false").";\n";
		$text.="    var fileRoot = '/'\n";
		$text.="    var showThumbs = 'false'\n";
		$text.="</script>\n";
		$text.="\n";
		$text.="<form id=\"uploader\" method=\"post\">\n";
		$text.="	<h1></h1>\n";
		$text.="	<div id=\"uploadresponse\"></div>\n";
		$text.="	<input id=\"mode\" name=\"" . $this->fmHttpVarsPrefix . "mode\" type=\"hidden\" value=\"add\" />\n";
		$text.="	<input id=\"currentpath\" name=\"currentpath\" type=\"hidden\" />\n";
		$text.="	<input id=\"newfile\" name=\"newfile\" type=\"file\" />\n";
		$text.="	<button id=\"upload\" name=\"upload\" type=\"submit\" value=\"Upload\">Upload</button>\n";
		$text.="	<button id=\"newfolder\" name=\"newfolder\" type=\"button\" value=\"New Folder\">New Folder</button>\n";
		$text.="	<button id=\"grid\" class=\"ON\" type=\"button\" title=\"Switch to grid view.\">&nbsp;</button><button id=\"list\" type=\"button\" title=\"Switch to list view.\">&nbsp;</button>\n";
		$text.="</form>\n";
		$text.="<div id=\"splitter\">\n";
		$text.="	<div id=\"filetree\"></div>\n";
		$text.="	<div id=\"fileinfo\"><h1>Select an item from the left.</h1></div>\n";
		$text.="</div>\n";
		$text.="\n";
		$text.="<ul id=\"itemOptions\" class=\"contextMenu\">\n";
		$text.="	<li class=\"select\"><a href=\"#select\">Select</a></li>\n";
		$text.="	<li class=\"download\"><a href=\"#download\">Download</a></li>\n";
		$text.="	<li class=\"rename\"><a href=\"#rename\">Rename</a></li>\n";
		$text.="	<li class=\"delete separator\"><a href=\"#delete\">Delete</a></li>\n";
		$text.="</ul>\n";
		
		
		if(!$returnText) {
			echo $text;
		}
		else {
			return $text;
		}
		
	}
	


	
	
}